home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
game
/
board
/
Crafty-15.19.lha
/
crafty-15.19
/
src
/
thread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-13
|
13KB
|
306 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "chess.h"
#include "data.h"
#include "epdglue.h"
/* modified 04/28/98 */
/*
********************************************************************************
* *
* Thread() is the driver for the threaded parallel search in Crafty. the *
* basic idea is that whenever we notice that one (or more) threads are *
* in their idle loop, we drop into thread, from Search(), and begin a new *
* parallel search from this node. this is simply a problem of copying the *
* search state space for each thread working at this node, then sending *
* everyone off to SearchSMP() to search this node in parallel. *
* *
********************************************************************************
*/
#if defined(SMP)
int Thread(TREE *tree) {
TREE *block;
int proc;
int nblocks=0;
/*
----------------------------------------------------------
| |
| first, we make sure that there are idle threads. it |
| is possible that we get here after they have all been |
| claimed by another thread. in that case we return. |
| |
----------------------------------------------------------
*/
Lock(lock_smp);
for (proc=0;proc<max_threads && thread[proc];proc++);
if (proc == max_threads || tree->stop) {
UnLock(lock_smp);
return(0);
}
# if defined(DEBUGSMP)
Lock(lock_io);
Print(128,"thread %d block %d ply %d parallel split\n",
tree->thread_id,FindBlockID(tree),tree->ply);
Print(128,"thread %d threads(s) idle:",tree->thread_id);
for (proc=0;proc<max_threads;proc++)
if (!thread[proc]) Print(128," %d",proc);
Print(128,"\n");
UnLock(lock_io);
#endif
/*
----------------------------------------------------------
| |
| now we start copying the current "state" from this |
| thread into new thread blocks so that the threads can |
| search this position without interfering with each |
| other. as we copy, we link those blocks as siblings |
| of the parent node, and point each sibling back to the |
| parent so we can unwind this confusion as the threads |
| complete their work. |
| |
----------------------------------------------------------
*/
thread[tree->thread_id]=0;
tree->nprocs=0;
tree->done=0;
for (proc=0;proc<max_threads;proc++) {
tree->siblings[proc]=0;
if (thread[proc] == 0) {
block=CopyToSMP(tree);
if (!block) continue;
nblocks++;
tree->siblings[proc]=block;
block->thread_id=proc;
block->parent=tree;
tree->nprocs++;
#if defined(DEBUGSMP)
Print(128,"thread %d block %d allocated at ply=%d\n",
proc,FindBlockID(block),tree->ply);
#endif
}
else tree->siblings[proc]=0;
}
tree->search_value=tree->value;
if (!nblocks) {
UnLock(lock_smp);
thread[tree->thread_id]=tree;
return(0);
}
/*
----------------------------------------------------------
| |
| everything is set. now we can stuff the address of |
| the thread blocks into thread[i] so that those idle |
| threads can begin the parallel search. |
| |
----------------------------------------------------------
*/
for (proc=0;proc<max_threads;proc++)
if (tree->siblings[proc])
thread[proc]=tree->siblings[proc];
/*
----------------------------------------------------------
| |
| after the threads are kicked off to start the parallel |
| search using the idle threads, this thread has to be |
| inserted as well. however, since it is possible that |
| this thread may finish before any or all of the other |
| parallel threads, this thread is sent to ThreadWait() |
| which will immediately send it to SearchSMP() just |
| like the other threads. going to ThreadWait() allows |
| this thread to join others if it runs out of work to |
| do. we do pass ThreadWait() the address of the parent |
| thread block, so that if this thread becomes idle, and |
| this thread block shows no threads are still busy, |
| then this thread can return to here and then back up |
| into the previous ply as it should. note that no |
| other thread can back up to the previous ply since |
| their recursive call stacks are not set for that. |
| |
----------------------------------------------------------
*/
UnLock(lock_smp);
ThreadWait(tree->thread_id, tree);
# if defined(DEBUGSMP)
Print(128,"thread %d block %d ply %d parallel join\n",
tree->thread_id,FindBlockID(tree), tree->ply);
#endif
return(1);
}
/* modified 04/09/98 */
/*
********************************************************************************
* *
* ThreadInit() is called from the pthread_create() function. it then calls *
* ThreadWait() with the appropriate arguments to park the new threads until *
* work is available. *
* *
********************************************************************************
*/
void *ThreadInit(void *tid) {
ThreadWait((int) tid, (TREE*) 0);
return(0);
}
/* modified 04/26/98 */
/*
********************************************************************************
* *
* ThreadStop() is called from SearchSMP() when it detects a beta cutoff (or *
* fail high) at a node that is being searched in parallel. we need to stop *
* all threads here, and since this threading algorithm is "recursive" it may *
* be necessary to stop other threads that are helping search this branch *
* further down into the tree. this function simply sets tree->stop to 1, *
* which will stop that particular thread instantly and return it to the idle *
* loop in ThreadWait(). *
* *
********************************************************************************
*/
void ThreadStop(TREE *tree) {
int proc;
Lock(tree->lock);
tree->stop=1;
for (proc=0;proc<max_threads;proc++)
if (tree->siblings[proc]) ThreadStop(tree->siblings[proc]);
UnLock(tree->lock);
#if defined(DEBUGSMP)
Lock(lock_io);
Print(128,"thread %d (block %d) being stopped by beta cutoff.\n",
tree->thread_id,FindBlockID(tree));
UnLock(lock_io);
#endif
}
/* modified 04/09/98 */
/*
********************************************************************************
* *
* ThreadWait() is the idle loop for the N threads that are created at the *
* beginning when Crafty searches. threads are "parked" here waiting on a *
* pointer to something they should search (a parameter block built in the *
* function Thread() in this case. when this pointer becomes non-zero, each *
* thread "parked" here will immediately call SearchSMP() and begin the *
* parallel search as directed. *
* *
********************************************************************************
*/
int ThreadWait(int tid, TREE *waiting) {
/*
----------------------------------------------------------
|